package com.suray.wcs.web.system.controller;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.enums.NodeStatus;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.annotation.InterfaceLog;
import com.suray.system.run.util.PortFuncUtil;
import com.suray.wcs.service.enums.*;
import com.suray.wcs.service.system.bo.ConnectNodeBO;
import com.suray.wcs.service.system.bo.NodeAndPlanBO;
import com.suray.wcs.service.system.entity.*;
import com.suray.wcs.service.system.service.IWareHouseDBService;
import com.suray.wcs.service.system.service.impl.*;
import com.suray.wcs.service.util.WcsUtil;
import com.suray.wcs.service.wmsconnect.*;
import com.suray.wcs.service.wmsconnect.dto.CargoNoDto;
import com.suray.wcs.service.wmsconnect.dto.NodeDto;
import com.suray.wcs.service.wmsconnect.dto.NodeListRequest;
import com.suray.wcs.service.wmsconnect.dto.WmsResonsesNodeDto;
import com.suray.wcs.web.system.jwt.exception.WmsTaskReceiveException;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.CollectionUtils;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/fromWms")
public class WmsConnectController {
    @Autowired
    TaskDBServiceImpl taskDBService;
    @Autowired
    NodeDBServiceImpl nodeDBService;
    @Autowired
    ProgrammeServiceImpl programmeService;

    @Autowired
    PortDBServiceImpl portDBService;
    @Autowired
    private IWareHouseDBService wareHouseDBService;
    @Autowired
    DeviceManagerServiceImpl deviceManagerServiceImpl;

    @Autowired
    private ConnectConfServiceImpl connectConfService;

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @ApiOperation(value = "任务接收")
    @PostMapping("/taskReceive")
    @InterfaceLog(value = "任务接收", sender = "WMS", recipient = "WCS")
    public WmsResponses taskReceive(@RequestBody WmsTask wmsTask) {
        log.info("接收到WMS下发的任务" + wmsTask.toString());
        try {
            int priorityCode = 1;
            if (wmsTask.getPriorityCode() != null) {
                priorityCode = wmsTask.getPriorityCode();
            }
            List<WmsTask.TasksBean> tasks = wmsTask.getTasks();
            String wareHouse = wmsTask.getWarehouse();
            List<TaskDB> taskDBS = new ArrayList<>();
            WareHouseDB wareHouseDB = wareHouseDBService.queryWareHouseByCode(wareHouse);
            if (wareHouseDB == null) {
                return WmsResponses.returnError(TaskReceiveResultEnum.DISTRICT_NOT_EXIST.getReturnStatus(), TaskReceiveResultEnum.DISTRICT_NOT_EXIST.getDescription() + wareHouse);
            }
            if (!wareHouseDBService.getIsAccept(wareHouseDB)) {
                return WmsResponses.returnError(TaskReceiveResultEnum.WCS_NOT_ACCEPT.getReturnStatus(), TaskReceiveResultEnum.WCS_NOT_ACCEPT.getDescription());
            }
            Collections.sort(tasks);
            for (WmsTask.TasksBean tasksBean : tasks) {
                WmsResponses wmsResponses = baseCheck(tasksBean);
                if (wmsResponses != null) {
                    return wmsResponses;
                }

                TaskType taskType;
                try {
                    taskType = TaskType.parseTaskType(tasksBean.getTaskType());
                } catch (Exception e) {
                    throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_TYPE_EXCEPTION.getReturnStatus(),
                            TaskReceiveResultEnum.TASK_TYPE_EXCEPTION.getDescription() + tasksBean.getTaskId());
                }

                TaskDB taskdb;
                if (taskType == TaskType.OUT && tasksBean.getEndNodes() != null && tasksBean.getEndNodes().size() > 0) {
                    //出库多库口
                    taskdb = chooseOutPorts(tasksBean, priorityCode);
                } else {
                    //入库任务 或则 出库任务没有多个库口 走原先的逻辑
                    taskdb = normalTaskReceive(tasksBean, priorityCode);
                }

                taskdb.setTaskType(taskType);
                taskdb.setBarCode(tasksBean.getBarCode());
                taskdb.setWmsTaskId(tasksBean.getTaskId());
                taskdb.setProcessingRgvNo(null);
                taskdb.setPriorityCode(priorityCode);
                taskDBS.add(taskdb);
            }
            for (TaskDB task : taskDBS) {
                if(task.getPreConnect() != null && task.getSufConnect() != null){
                    splitTask(task);
                } else {
                    taskDBService.insertTask(Collections.singletonList(task));
                }

                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("接收到WMS任务并插入" + task);
            }
            return WmsResponses.returnSuccess();
        } catch (Exception e) {
            WcsFuncUtil.exceptionLog(e, this.getClass());
            return WmsResponses.returnError(e.getMessage());
        }
    }

    /**
     * 多库口出库任务
     * @param tasksBean
     * @param priorityCode
     * @return
     */
    private TaskDB chooseOutPorts(WmsTask.TasksBean tasksBean, int priorityCode) {
        if (!tasksBean.getTaskType().equals(TaskType.OUT.getTypeNum())) {
            throw new RuntimeException("不是出库任务，调用方法错误:" + tasksBean);
        }

        if (tasksBean.getEndNodes().size() == 0) {
            if (tasksBean.getEndNode() == null) {
                throw new RuntimeException("多库口出库，没有给库口，无法选择最终出库口");
            }

            return normalTaskReceive(tasksBean, priorityCode);
        } else if (tasksBean.getEndNodes().size() == 1) {
            String port = tasksBean.getEndNodes().get(0);
            if (isPortEnable(port, tasksBean.getTaskType())) {
                throw new RuntimeException("库口" + port + "无法使用，无法出库，请选择其它出库口");
            }
            tasksBean.setEndNode(port);
            return normalTaskReceive(tasksBean, priorityCode);
        }

        return generalOutTaskByPorts(tasksBean, priorityCode);
    }

    /**
     * 传入portcode 确认port是否启用
     * @param portCode
     * @return
     */
    private boolean isPortEnable(String portCode, Integer taskType) {
        PortDB portDB = portDBService.selectByPortCode(portCode);
        if (!PortFuncUtil.isPortEnable(portDB)) {
            return false;
        }

        PortModel portModel = PortModel.parsePortType(portDB.getPortMode());
        switch (portModel) {
            case IN_PORT:
                if (taskType == TaskType.IN.getTypeNum()) {
                    return true;
                }
            case OUT_PORT:
                if (taskType == TaskType.OUT.getTypeNum()) {
                    return true;
                }
            case TRANSFER_PORT:
                if (taskType == TaskType.TRANSFER.getTypeNum()) {
                    return true;
                }
            case IN_AND_OUT:
                if (taskType == TaskType.IN.getTypeNum() || taskType == TaskType.OUT.getTypeNum()) {
                    return true;
                }
            case BAN:
            default:
                break;
        }

        return false;
    }

    /**
     * 生成多库口出库任务
     * @param tasksBean
     * @param priorityCode
     * @return
     */
    private TaskDB generalOutTaskByPorts(WmsTask.TasksBean tasksBean, int priorityCode) {
        List<String> endPorts = tasksBean.getEndNodes();

        boolean canOut = false;
        for (String endPort : endPorts) {
            if (isPortEnable(endPort, tasksBean.getTaskType())) {
                canOut = true;
                break;
            }
        }

        if (!canOut) {
            throw new RuntimeException("库口当前都无法使用，无法出库:" + WcsFuncUtil.listToString(endPorts));
        }

        TaskDB taskdb = new TaskDB();
        // 根据WMS发送的任务起点和终点找到小车的起点和终点
        NodeDB rgvStartSNode;
        try {
            rgvStartSNode = getRgvStartNode(tasksBean);
        } catch (Exception e) {
            log.error("查找起点出现异常", e);
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_START_HAS_ERROR.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_START_HAS_ERROR.getDescription() + tasksBean.getTaskId());
        }

        if (rgvStartSNode == null) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_NO_START.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_NO_START.getDescription() + tasksBean.getTaskId());
        }

        if (rgvStartSNode == null) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_START_NOT_EXIST.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_START_NOT_EXIST.getDescription() + tasksBean.getTaskId());
        }

        if (tasksBean.getTaskType() == TaskType.OUT.getTypeNum()
                && rgvStartSNode.getGridStatus().equals(NodeStatus.N.toString())) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_OUT_START_NO_GOODS.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_OUT_START_NO_GOODS.getDescription() + tasksBean.getTaskId());
        }

        Node startNode = new Node(rgvStartSNode.getGridx(), rgvStartSNode.getGridy(), rgvStartSNode.getGridz());

        taskdb.setStartNode(startNode);
        taskdb.setPriorityCode(priorityCode);
        taskdb.setOutPortsStr(PortFuncUtil.changeToPortsStr(findPortsByPortCodes(tasksBean.getEndNodes())));

        return taskdb;
    }

    private List<PortDB> findPortsByPortCodes(List<String> portCodes) {
        List<PortDB> portDBS = new ArrayList<>();
        List<PortDB> ports = portDBService.list();
        for (String portCode : portCodes) {
            for (PortDB portDB : ports) {
                if (portCode.equals(portDB.getPortCode())) {
                    portDBS.add(portDB);
                }
            }
        }

        return portDBS;
    }

    /**
     * 正常出入库任务
     * @param tasksBean
     * @param priorityCode
     * @return
     */
    private TaskDB normalTaskReceive(WmsTask.TasksBean tasksBean, int priorityCode) {
        ConnectNodeBO startPlanBO = null;
        ConnectNodeBO endPlanBO = null;
        TaskDB taskdb = new TaskDB();
        // 根据WMS发送的任务起点和终点找到小车的起点和终点
        NodeDB rgvStartSNode;
        NodeDB rgvEndSNode;
        try {
            rgvStartSNode = getRgvStartNode(tasksBean);
        } catch (Exception e) {
            log.error("查找起点出现异常", e);
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_START_HAS_ERROR.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_START_HAS_ERROR.getDescription() + tasksBean.getTaskId());
        }
        try {
            rgvEndSNode = getRgvEndNode(tasksBean);
        } catch (Exception e) {
            log.error("查找终点出现异常", e);
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_END_HAS_ERROR.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_END_HAS_ERROR.getDescription() + tasksBean.getTaskId());
        }
        // 入库起点为空，未找到最适合的入库方案起点，则寻找接驳配置
        if (tasksBean.getTaskType() == TaskType.IN.getTypeNum() && rgvStartSNode == null) {
            if (rgvEndSNode == null) {
                throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_END_NOT_EXIST.getReturnStatus(),
                        TaskReceiveResultEnum.TASK_END_NOT_EXIST.getDescription() + tasksBean.getTaskId());
            }
            startPlanBO = WcsUtil.getConnectNodeInOrOut(tasksBean.getStartNode(), tasksBean.getEndNode(), null,
                    rgvEndSNode, TaskType.IN.getTypeNum(), nodeDBService, connectConfService);

            if (startPlanBO == null) {
                log.error("上位任务：{}无法找到适合的入库方案和接驳方案！", tasksBean.getTaskId());
                throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_START_HAS_ERROR.getReturnStatus(),
                        TaskReceiveResultEnum.TASK_START_HAS_ERROR.getDescription() + tasksBean.getTaskId());
            }
            rgvStartSNode = startPlanBO.getNodedb();
        }

        if (rgvStartSNode == null) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_NO_START.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_NO_START.getDescription() + tasksBean.getTaskId());
        }

        if (tasksBean.getTaskType() == TaskType.OUT.getTypeNum() && rgvEndSNode == null) {
            if (rgvStartSNode == null) {
                throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_START_NOT_EXIST.getReturnStatus(),
                        TaskReceiveResultEnum.TASK_START_NOT_EXIST.getDescription() + tasksBean.getTaskId());
            }
            endPlanBO = WcsUtil.getConnectNodeInOrOut(tasksBean.getStartNode(), tasksBean.getEndNode(), rgvStartSNode,
                    null, TaskType.OUT.getTypeNum(), nodeDBService, connectConfService);

            if (endPlanBO == null) {
                log.error("上位任务：{}无法找到适合的出库方案和接驳方案！", tasksBean.getTaskId());
                throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_END_HAS_ERROR.getReturnStatus(),
                        TaskReceiveResultEnum.TASK_END_HAS_ERROR.getDescription() + tasksBean.getTaskId());
            }
            rgvEndSNode = endPlanBO.getNodedb();
        }

        if (rgvEndSNode == null) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_NO_END.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_NO_END.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() == TaskType.TRANSFER.getTypeNum()
                && rgvStartSNode.getGridStatus().equals(NodeStatus.N.toString()) && NodeType.P.equals(rgvStartSNode.getGridType())) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_TRANSFER_START_NO_GOODS.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_TRANSFER_START_NO_GOODS.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() == TaskType.TRANSFER.getTypeNum()
                && rgvEndSNode.getGridStatus().equals(NodeStatus.Y.toString())) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_TRANSFER_END_HAS_GOODS.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_TRANSFER_END_HAS_GOODS.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() == TaskType.IN.getTypeNum()
                && rgvEndSNode.getGridStatus().equals(NodeStatus.Y.toString())) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_IN_END_HAS_GOODS.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_IN_END_HAS_GOODS.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() == TaskType.OUT.getTypeNum()
                && rgvStartSNode.getGridStatus().equals(NodeStatus.N.toString())) {
            throw new WmsTaskReceiveException(TaskReceiveResultEnum.TASK_OUT_START_NO_GOODS.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_OUT_START_NO_GOODS.getDescription() + tasksBean.getTaskId());
        }
        Node startNode = new Node(rgvStartSNode.getGridx(), rgvStartSNode.getGridy(), rgvStartSNode.getGridz());
        Node endNode = new Node(rgvEndSNode.getGridx(), rgvEndSNode.getGridy(), rgvEndSNode.getGridz());

        // 移库任务起点和终点不同层，则判断是否接驳
        if (tasksBean.getTaskType() == TaskType.TRANSFER.getTypeNum() && startNode.getZ() != endNode.getZ()) {
            endPlanBO = getConnectNodeOther(startNode, endNode, TaskType.TRANSFER.getTypeNum());
        }
        taskdb.setStartNode(startNode);
        taskdb.setEndNode(endNode);
        if (startPlanBO != null) {
            taskdb.setPreConnect(startPlanBO.getPreConnect());
            taskdb.setSufConnect(startPlanBO.getSufNodeConnect());
            taskdb.setConnectPortCode(startPlanBO.getConnectPortCode());
        } else if (endPlanBO != null) {
            taskdb.setPreConnect(endPlanBO.getPreConnect());
            taskdb.setSufConnect(endPlanBO.getSufNodeConnect());
            taskdb.setConnectPortCode(endPlanBO.getConnectPortCode());
        }

        if (tasksBean.getTaskType() == TaskType.IN.getTypeNum()) {
            taskdb.setTaskPortId(tasksBean.getStartNode());
        } else if (tasksBean.getTaskType() == TaskType.OUT.getTypeNum()) {
            taskdb.setTaskPortId(tasksBean.getEndNode());
        }

        return taskdb;
    }

    /**
     * 从WMS接受到的任务做基础校验
     *
     * @param tasksBean
     * @return
     */
    private WmsResponses baseCheck(WmsTask.TasksBean tasksBean) {
        if (tasksBean == null || tasksBean.getTaskId() == null) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_ID_IS_NULL.getReturnStatus(), TaskReceiveResultEnum.TASK_ID_IS_NULL.getDescription());
        }
        if (tasksBean.getTaskId() == null || StringUtils.isEmpty(tasksBean.getTaskId())) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_ID_IS_NULL.getReturnStatus(), TaskReceiveResultEnum.TASK_ID_IS_NULL.getDescription());
        }
        if (taskDBService.queryTaskInfoByWMSId(tasksBean.getTaskId()) != null) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_ID_EXIST.getReturnStatus(), TaskReceiveResultEnum.TASK_ID_EXIST.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() == null) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_TYPE_EXCEPTION.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_TYPE_EXCEPTION.getDescription() + tasksBean.getTaskId());
        }
        if (StringUtils.isEmpty(tasksBean.getStartNode())) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_NO_START.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_NO_START.getDescription() + tasksBean.getTaskId());
        }
        if (StringUtils.isEmpty(tasksBean.getEndNode())) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_NO_END.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_NO_END.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() == TaskType.IN.getTypeNum()) {
            PortDB portDB = portDBService.selectByPortCode(tasksBean.getStartNode());
            if (portDB == null) {
                return WmsResponses.returnError(TaskReceiveResultEnum.NO_IN_PORT.getReturnStatus(),
                        TaskReceiveResultEnum.NO_IN_PORT.getDescription() + tasksBean.getTaskId());
            }
        }
        if (tasksBean.getTaskType() == TaskType.OUT.getTypeNum()) {
            PortDB portDB = portDBService.selectByPortCode(tasksBean.getEndNode());
            if (portDB == null) {
                return WmsResponses.returnError(TaskReceiveResultEnum.NO_OUT_PORT.getReturnStatus(),
                        TaskReceiveResultEnum.NO_OUT_PORT.getDescription() + tasksBean.getTaskId());
            }
        }
        if (tasksBean.getTaskType() != TaskType.IN.getTypeNum() && nodeDBService.getNodeDBByGridID(tasksBean.getStartNode()) == null) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_START_NOT_EXIST.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_START_NOT_EXIST.getDescription() + tasksBean.getTaskId());
        }
        if (tasksBean.getTaskType() != TaskType.OUT.getTypeNum() && nodeDBService.getNodeDBByGridID(tasksBean.getEndNode()) == null) {
            return WmsResponses.returnError(TaskReceiveResultEnum.TASK_END_NOT_EXIST.getReturnStatus(),
                    TaskReceiveResultEnum.TASK_END_NOT_EXIST.getDescription() + tasksBean.getTaskId());
        }
        return null;
    }

    @PostMapping("/deviceStatus")
    @ResponseBody
    @ApiOperation(value = "返回设备信息")
    @InterfaceLog(value = "设备信息查询", sender = "WMS", recipient = "WCS")
    public List<ReturnMsgDevice> deviceReceive(@RequestBody GetDeviceInfo msgGetDeviceBean) {
        List<ReturnMsgDevice> devices = new ArrayList<ReturnMsgDevice>();
        Integer deviceId = msgGetDeviceBean.getDeviceNo();
        Integer deviceType = msgGetDeviceBean.getDeviceType();
        if (deviceId == null) {
            if (deviceType != null) {
                deviceManagerServiceImpl.fillDevicesIdNullTypeNotNull(devices, deviceType);
            } else {
                deviceManagerServiceImpl.fillDevicesIdNullTypeNull(devices, deviceType);
            }
        } else {
            if (deviceType != null) {
                deviceManagerServiceImpl.fillDevicesIdNotNullTypeNotNull(devices, deviceId, deviceType);
            } else {
                deviceManagerServiceImpl.fillDevicesIdNotNullTypeNull(devices, deviceId, deviceType);
            }
        }
        return devices;
    }

    @PostMapping("/taskCancel")
    @ResponseBody
    @ApiOperation(value = "任务取消接口")
    @InterfaceLog(value = "任务取消接口", sender = "WMS", recipient = "WCS")
    public WmsResponses taskCancel(@RequestBody TaskCancelRequest taskCancelRequest) {
        if (taskCancelRequest.getTaskId().isEmpty()) {
            return WmsResponses.returnError("任务编号不可为空！");
        }
        TaskDB taskdb = taskDBService.queryTaskInfoByWMSId(taskCancelRequest.getTaskId());
        if (taskdb == null) {
            return WmsResponses.returnError("不存在的任务，无法取消！");
        }
        if (taskdb.getTaskStatus() != TaskStatus.NEW && taskdb.getTaskStatus() != TaskStatus.WAIT
                && taskdb.getTaskStatus() != TaskStatus.ERROR) {
            return WmsResponses.returnError("只可取消故障或者未开始执行的任务！");
        }
        taskDBService.updateTaskStatus(taskdb, TaskStatus.CANCEL);
        String value = Plc.PLC_INTERRUPT_CACHE.get(String.valueOf(taskdb.getTaskId()));
        if (!org.springframework.util.StringUtils.isEmpty(value)) {
            Plc.PLC_INTERRUPT_CACHE.remove(String.valueOf(taskdb.getTaskId()));
        }
        return WmsResponses.returnSuccess();
    }

    @PostMapping("/taskPriority")
    @ResponseBody
    @ApiOperation(value = "调整优先级")
    @InterfaceLog(value = "调整优先级", sender = "WMS", recipient = "WCS")
    public WmsResponses taskPriority(@RequestBody AdjustPriority adjustPriority) {
        if (adjustPriority.getTaskId().isEmpty()) {
            return WmsResponses.returnError("任务编号不可为空！");
        }
        TaskDB taskdb = taskDBService.queryTaskInfoByWMSId(adjustPriority.getTaskId());
        if (taskdb == null) {
            return WmsResponses.returnError("不存在的任务，无法调整优先级！");
        }
        if (taskdb.getTaskStatus() != TaskStatus.NEW && taskdb.getTaskStatus() != TaskStatus.WAIT
                && taskdb.getTaskStatus() != TaskStatus.ERROR) {
            return WmsResponses.returnError("只可调整故障或者未开始执行的任务！");
        }
        taskdb.setPriorityCode(adjustPriority.getPriorityCode());
        taskDBService.updateSortCode(taskdb);
        return WmsResponses.returnSuccess();
    }

    /**
     * 根据WMS发送的任务获取小车的起点
     */
    private NodeDB getRgvStartNode(WmsTask.TasksBean tasksBean) {
        if (tasksBean.getTaskType().equals(TaskType.IN.getTypeNum())) {
            NodeDB end = nodeDBService.getNodeDBByGridID(tasksBean.getEndNode());
            Node node = new Node(end.getGridx(), end.getGridy(), end.getGridz());
            NodeAndPlanBO nodeAndPlanBO = nodeDBService.getMostAccessibleNodeAndPlan(tasksBean.getStartNode(), node.toString(),
                    TaskType.parseTaskType(tasksBean.getTaskType()));
            if(!ConnectModel.NEED_CONNECT.getValue().equals(portDBService.selectByPortCode(tasksBean.getStartNode()).getConnectMode())){
                if(nodeAndPlanBO == null){
                    throw new RuntimeException("无法根据库口找到合适的起/终点");
                }
            }
            return nodeAndPlanBO != null ? nodeAndPlanBO.getNodedb() : null;
        } else {
            return nodeDBService.getNodeDBByGridID(tasksBean.getStartNode());
        }
    }

    /**
     * 根据WMS发送的任务获取小车的终点
     */
    private NodeDB getRgvEndNode(WmsTask.TasksBean tasksBean) {
        if (tasksBean.getTaskType().equals(TaskType.OUT.getTypeNum())) {
            NodeDB start = nodeDBService.getNodeDBByGridID(tasksBean.getStartNode());
            Node node = new Node(start.getGridx(), start.getGridy(), start.getGridz());
            NodeAndPlanBO nodeAndPlanBO = nodeDBService.getMostAccessibleNodeAndPlan(node.toString(), tasksBean.getEndNode(),
                    TaskType.parseTaskType(tasksBean.getTaskType()));
            if(!ConnectModel.NEED_CONNECT.getValue().equals(portDBService.selectByPortCode(tasksBean.getEndNode()).getConnectMode())){
                if(nodeAndPlanBO == null){
                    throw new RuntimeException("无法根据库口找到合适的起/终点");
                }
            }
            return nodeAndPlanBO != null ? nodeAndPlanBO.getNodedb() : null;
        } else {
            return nodeDBService.getNodeDBByGridID(tasksBean.getEndNode());
        }
    }

    /**
     * 入库和出库根据WMS发送的任务获取最优的接驳配置
     */
    private ConnectNodeBO getConnectNodeInOrOut(String startStr, String endStr, NodeDB start, NodeDB end, Integer taskType) {
        // 接驳点方案集合
        List<ConnectConfDB> connectDBList;
        ConnectNodeBO connectNodeBO = null;

        if (taskType.equals(TaskType.IN.getTypeNum())) {
            Node node = new Node(end.getGridx(), end.getGridy(), end.getGridz());
            connectDBList = connectConfService.findByType(PortModel.IN_PORT.getValue());
            // 最适合的入库接驳配置方案
            connectNodeBO = nodeDBService.getMostConnectNodeAndPlan(startStr, node.toString(),
                    TaskType.parseTaskType(taskType), connectDBList);
        } else if (taskType.equals(TaskType.OUT.getTypeNum())) {
            Node node = new Node(start.getGridx(), start.getGridy(), start.getGridz());
            connectDBList = connectConfService.findByType(PortModel.OUT_PORT.getValue());
            // 最适合的出库接驳配置方案
            connectNodeBO = nodeDBService.getMostConnectNodeAndPlan(node.toString(), endStr,
                    TaskType.parseTaskType(taskType), connectDBList);
        }
        return connectNodeBO;
    }

    /**
     * 移库或搬运任务根据WMS发送的任务获取最优的接驳配置
     */
    private ConnectNodeBO getConnectNodeOther(Node start, Node end, int taskType) {
        // 接驳点方案集合
        List<ConnectConfDB> connectDBList;
        ConnectNodeBO connectNodeBO;

        connectDBList = connectConfService.findByType(PortModel.TRANSFER_PORT.getValue());
        connectNodeBO = nodeDBService.getMostConnectNodeAndPlan(start.toString(), end.toString(),
                TaskType.parseTaskType(taskType), connectDBList);

        return connectNodeBO;
    }

    /**
     * Nodedb 转换成Node
     *
     * @param Nodedb
     * @return
     */
    public static Node parseNodeDB(NodeDB Nodedb) {
        if (Nodedb == null) return null;
        int x = Nodedb.getGridx();
        int y = Nodedb.getGridy();
        int z = Nodedb.getGridz();
        return new Node(x, y, z);
    }

    /**
     * @param cargos
     * @return CargoRtnMsg
     * @Description:货位信息同步 WCS系统中如果存在货位状态（是否有货）与上位系统不一致的情况 则在上位系统中人工确认后通过该接口与速锐WCS同步
     * @author rbj
     */
    @PostMapping("/cargoLocationSyn")
    @ApiOperation(value = "货位信息同步")
    public CargoRtnMsg cargoLocationSyn(@RequestBody List<CargoFromWms> cargos) {
        List<NodeDB> nodeDBS = new ArrayList<>();
        CargoRtnMsg cargoRtnMsg = new CargoRtnMsg();
        NodeDB nodeDBs;
        int failureNum = 0;
        StringBuffer successMsg = new StringBuffer();
        StringBuffer failureMsg = new StringBuffer();
        for (CargoFromWms cargoFromWMS : cargos) {
            nodeDBs = nodeDBService.getNodeDBByGridID(cargoFromWMS.getCargoLocationId());
            if (nodeDBs != null) {
                nodeDBs.setGridStatus(cargoFromWMS.getCargoLocationStatus());
                nodeDBS.add(nodeDBs);
            } else {
                failureNum++;
                failureMsg.append("<br/>" + cargoFromWMS.getCargoLocationId() + "不存在.");
            }
        }
        if (!CollectionUtils.isEmpty(nodeDBS)) {
            nodeDBService.updateBatchById(nodeDBS, nodeDBS.size());
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据无法同步，错误如下：");
            cargoRtnMsg.setReturnInfo(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + nodeDBS.size() + " 条");
            cargoRtnMsg.setReturnInfo(successMsg.toString());
        }
        successMsg.append(failureMsg);
        cargoRtnMsg.setMsgTime(new Date());
        cargoRtnMsg.setReturnStatus(0);
        return cargoRtnMsg;
    }


    /**
     * @param nodeListRequest
     * @return String
     * @Description:WMS货位信息查询接口
     * @author rbj
     */
    @PostMapping("/cargoLocationStatus")
    @ResponseBody
    @ApiOperation(value = "货位状态查询")
    public WmsResonsesNodeDto cargoLocationStatus(@RequestBody NodeListRequest nodeListRequest) {
        log.info("接收到上位系统<货位状态查询>请求，参数-->" + nodeListRequest);
        Integer layer = nodeListRequest.getLayer();
        String cargoLocationId = nodeListRequest.getCargoLocationId();
        String returnInfo = "";
        List<NodeDto> nodeDtoList = Lists.newArrayList();
        if (layer == null) {
            returnInfo = "查询失败，请填写当前层";
            return WmsResonsesNodeDto.returnError(returnInfo, nodeDtoList);
        }

        if (StringUtils.isBlank(cargoLocationId)) {
            List<NodeDB> nodeDBList = nodeDBService.getNodeDBByFloorAndType(NodeType.P.getCode(), layer);
            if (!CollectionUtils.isEmpty(nodeDBList)) {
                for (NodeDB nodedb : nodeDBList) {
                    nodeDtoList.add(buildNodeDto(nodedb));
                }
                returnInfo = "查询第" + layer + "层货位信息成功";
            }
        } else {
            NodeDB nodeDBRes = nodeDBService.getNodeDBByGridID(cargoLocationId);
            if (nodeDBRes == null) {
                returnInfo = "查询失败，货位编码为：" + cargoLocationId + "未找到";
                return WmsResonsesNodeDto.returnError(returnInfo, nodeDtoList);
            } else {
                nodeDtoList.add(buildNodeDto(nodeDBRes));
                returnInfo = "查询成功";
            }
        }
        return WmsResonsesNodeDto.returnSuccess(returnInfo, nodeDtoList);
    }

    private NodeDto buildNodeDto(NodeDB nodeDB) {
        NodeDto nodeDto = new NodeDto();
        nodeDto.setCargoLocationId(nodeDB.getGridId());
        nodeDto.setCargoLocationStatus(nodeDB.getGridStatus());
        nodeDto.setPalletCode(nodeDB.getPalletCode());
        return nodeDto;
    }

    @PostMapping("/cargoNoSyn")
    @ResponseBody
    @ApiOperation(value = "货位编码同步")
    public WmsResponses cargoNoSyn(@RequestBody List<CargoNoDto> cargoNoDtos) {
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<NodeDB> nodeDBs = nodeDBService.list();
        List<NodeDB> nodeDBList = new ArrayList<>();
        for (CargoNoDto cargoNoDto : cargoNoDtos) {
            // 过滤
            List<NodeDB> collect = nodeDBs.stream().filter(nodeDB1 ->
                    nodeDB1.getGridx().equals(cargoNoDto.getPosiX()) && nodeDB1.getGridy().equals(cargoNoDto.getPosiY()) && nodeDB1.getGridz().equals(cargoNoDto.getPosiZ())
            ).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(collect)) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、货位 " + cargoNoDto.getCargoNo() + " 不存在");
            } else if (collect.size() > 1) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、货位 " + cargoNoDto.getCargoNo() + " 存在多个");
            } else {
                NodeDB nodeDB = collect.get(0);
                if (!nodeDB.getGridType().equals(NodeType.P)) {
                    successMsg.append("<br/>" + failureNum + "、货位 " + cargoNoDto.getCargoNo() + " 在WCS不是货位！");
                }
                nodeDB.setGridId(cargoNoDto.getCargoNo());
                nodeDBList.add(nodeDB);
            }
        }
        nodeDBService.updateBatchById(nodeDBList, nodeDBList.size());
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据无法同步，错误如下：");
            return WmsResponses.returnSuccess(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部同步成功！共 " + nodeDBList.size() + " 条");
            return WmsResponses.returnSuccess(successMsg.toString());
        }

    }


    @PostMapping("/taskChange")
    @ResponseBody
    @ApiOperation(value = "任务目的位置更改接口")
    @InterfaceLog(value = "任务目的位置更改接口", sender = "WMS", recipient = "WCS")
    public WmsResponses taskChange(@RequestBody TaskUpdateEnd taskUpdateEnd) {
        //根据任务id查询这条任务
        String taskId = taskUpdateEnd.getTaskId();
        TaskDB taskDB = taskDBService.queryTaskInfoByWMSId(taskId);
        NodeDB nodeDBByGridID = nodeDBService.getNodeDBByGridID(taskUpdateEnd.getEndNode());
        if (taskDB == null) {
            return WmsResponses.returnError("不存在的任务，无法更改目的位置！");
        }
        if (!taskDB.getTaskStatus().equals(TaskStatus.ERROR)) {
            return WmsResponses.returnError("非故障任务无法改变目的位置！");
        }
        if (nodeDBByGridID == null) {
            return WmsResponses.returnError("目的位置不存在！");
        }
        if (!nodeDBByGridID.getGridType().equals(NodeType.P)) {
            return WmsResponses.returnError("更改目的坐标不是货位！");
        }
        if (nodeDBByGridID.getGridStatus().equals(NodeStatus.Y.toString())) {
            return WmsResponses.returnError("更改目的坐标已有货物！");
        }
        taskDB.setEndNode(parseNodeDB(nodeDBByGridID));
        //更改任务目的坐标
        boolean result = taskDBService.updateById(taskDB);
        //0- 成功; 1- 失败
        if (result) {
            return WmsResponses.returnSuccess("操作成功");
        } else {
            return WmsResponses.returnError("操作失败！");
        }
    }


    @PostMapping("/portModel")
    @ResponseBody
    @ApiOperation(value = "库口模式切换")
    @InterfaceLog(value = "库口模式切换", sender = "WMS", recipient = "WCS")
    public WmsResponses portModel(@RequestBody PortUpdateDB portUpdateDB) {
        String portCode = portUpdateDB.getPortCode();
        String warehouse = portUpdateDB.getWarehouse();
        //0入库 1出库 2禁用
        Integer portModel = portUpdateDB.getPortModel();
        log.info("接收到上位系统<库区模式切换>请求，参数-->" + portUpdateDB);
        if (!PortModel.IN_PORT.getValue().equals(portModel) &&
                !PortModel.OUT_PORT.getValue().equals(portModel) &&
                !PortModel.BAN.getValue().equals(portModel)) {
            return WmsResponses.returnError("要修改的库区模式不符合");
        }
        //当前库区对象
        WareHouseDB curWareHouseDB = wareHouseDBService.getCurWareHouseDB();
        if (!curWareHouseDB.getWarehouseCode().equals(warehouse)) {
            return WmsResponses.returnError("仓库编码不符合");
        }
        //根据库口编码查询是否有此库口
        PortDB portDB = portDBService.selectByPortCode(portCode);
        if (portDB == null) {
            return WmsResponses.returnError("未找到此库口");
        } else {
            //根据库口编码  找到这条数据  更改库口模式
            portDB.setPortMode(portModel);
            Boolean result = portDBService.updateById(portDB);
            if (result) {
                return WmsResponses.returnSuccess("操作成功");
            } else {
                return WmsResponses.returnError("操作失败！");
            }
        }
    }


    /**
     * 接驳任务
     *
     * @param taskDB
     */
    private void splitTask(TaskDB taskDB) {
        TaskDB preTask = new TaskDB();
        preTask.setStartNode(taskDB.selectStartNode());
        preTask.setEndNode(taskDB.getPreConnect());
        if (TaskType.TRANSFER.equals(taskDB.getTaskType())) {
            preTask.setTaskType(TaskType.OUT);
        } else {
            preTask.setTaskType(taskDB.getTaskType());
        }
        if (TaskType.IN.equals(preTask.getTaskType())) {
            preTask.setTaskPortId(taskDB.getTaskPortId());
        } else {
            preTask.setTaskPortId(taskDB.getConnectPortCode());
        }
        preTask.setPriorityCode(taskDB.getPriorityCode());
        preTask.setBarCode(taskDB.getBarCode());
        preTask.setWmsTaskId(null);

        taskDBService.insertTask(Collections.singletonList(preTask));

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        TaskDB sufTask = new TaskDB();
        sufTask.setStartNode(taskDB.getSufConnect());
        sufTask.setEndNode(taskDB.selectEndNode());
        if (TaskType.OUT.equals(taskDB.getTaskType())) {
            sufTask.setTaskPortId(taskDB.getTaskPortId());
        } else {
            sufTask.setTaskPortId(taskDB.getConnectPortCode());
        }
        sufTask.setTaskType(taskDB.getTaskType());
        sufTask.setPriorityCode(taskDB.getPriorityCode());
        sufTask.setBarCode(taskDB.getBarCode());
        sufTask.setWmsTaskId(taskDB.getWmsTaskId());
        sufTask.setPreTaskId(preTask.getTaskId());

        taskDBService.insertTask(Collections.singletonList(sufTask));
    }
}
